From 067b2412697ff2155e1d429aafda787188fdbcfa Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Fri, 6 Aug 2004 09:35:45 +0000 Subject: [PATCH] bitkeeper revision 1.1155 (411350f1WPGKHyDE_nv5WX9LJBbaWg) Add support for marking bad pages using the 'badpage=xxx' cmdline option when booting Xen. --- README.CD | 7 ++++++ docs/HOWTOs/Xen-HOWTO | 7 ++++++ docs/user.tex | 8 ++++++ xen/common/kernel.c | 53 ++++++++++++++++++++++---------------- xen/common/page_alloc.c | 56 ++++++++++++++++++++++------------------- xen/include/xen/lib.h | 2 +- 6 files changed, 85 insertions(+), 48 deletions(-) diff --git a/README.CD b/README.CD index fcf94be18f..3ea9eb7639 100644 --- a/README.CD +++ b/README.CD @@ -277,6 +277,13 @@ that may be able to help diagnose problems: noht Disable Hyperthreading. + badpage=[,]* + Specify a list of pages not to be allocated for use + because they contain bad bytes. For example, if your + memory tester says that byte 0x12345678 is bad, you would + place 'badpage=0x12345' on Xen's command line (i.e., the + last three digits of the byte address are not included!). + com1=,DPS[,,] com2=,DPS[,,] Xen supports up to two 16550-compatible serial ports. diff --git a/docs/HOWTOs/Xen-HOWTO b/docs/HOWTOs/Xen-HOWTO index 272670baa1..62cbfc6888 100644 --- a/docs/HOWTOs/Xen-HOWTO +++ b/docs/HOWTOs/Xen-HOWTO @@ -223,6 +223,13 @@ The following is a list of command line arguments to pass to Xen: noht Disable Hyperthreading. + badpage=[,]* + Specify a list of pages not to be allocated for use + because they contain bad bytes. For example, if your + memory tester says that byte 0x12345678 is bad, you would + place 'badpage=0x12345' on Xen's command line (i.e., the + last three digits of the byte address are not included!). + com1=,DPS[,,] com2=,DPS[,,] Xen supports up to two 16550-compatible serial ports. diff --git a/docs/user.tex b/docs/user.tex index e13c1a50d0..bdb546b853 100644 --- a/docs/user.tex +++ b/docs/user.tex @@ -1140,6 +1140,14 @@ editting \path{grub.conf}. {\bf noht } \\ Disable Hyperthreading. \\ +{\bf badpage=$<$page number$>$[,$<$page number$>$] } \\ + Specify a list of pages not to be allocated for use + because they contain bad bytes. For example, if your + memory tester says that byte 0x12345678 is bad, you would + place 'badpage=0x12345' on Xen's command line (i.e., the + last three digits of the byte address are not + included!). \\ + {\bf com1=$<$baud$>$,DPS[,$<$io\_base$>$,$<$irq$>$] \\ com2=$<$baud$>$,DPS[,$<$io\_base$>$,$<$irq$>$] } \\ Xen supports up to two 16550-compatible serial ports. diff --git a/xen/common/kernel.c b/xen/common/kernel.c index de9e1c26c9..6a39946d70 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -91,32 +91,40 @@ char opt_nmi[10] = "dom0"; #else char opt_nmi[10] = "fatal"; #endif +/* + * Comma-separated list of hexadecimal page numbers containing bad bytes. + * e.g. 'badpage=0x3f45,0x8a321'. + */ +char opt_badpage[100] = ""; static struct { unsigned char *name; enum { OPT_STR, OPT_UINT, OPT_BOOL } type; void *var; + unsigned int len; } opts[] = { - { "console", OPT_STR, &opt_console }, - { "conswitch", OPT_STR, &opt_conswitch }, - { "com1", OPT_STR, &opt_com1 }, - { "com2", OPT_STR, &opt_com2 }, - { "dom0_mem", OPT_UINT, &opt_dom0_mem }, - { "noht", OPT_BOOL, &opt_noht }, - { "noacpi", OPT_BOOL, &opt_noacpi }, - { "nosmp", OPT_BOOL, &opt_nosmp }, - { "noreboot", OPT_BOOL, &opt_noreboot }, - { "ignorebiostables", OPT_BOOL, &opt_ignorebiostables }, - { "watchdog", OPT_BOOL, &opt_watchdog }, - { "pdb", OPT_STR, &opt_pdb }, - { "tbuf_size", OPT_UINT, &opt_tbuf_size }, - { "sched", OPT_STR, &opt_sched }, - { "physdev_dom0_hide", OPT_STR, &opt_physdev_dom0_hide }, - { "leveltrigger", OPT_STR, &opt_leveltrigger }, - { "edgetrigger", OPT_STR, &opt_edgetrigger }, - { "xenheap_megabytes", OPT_UINT, &opt_xenheap_megabytes }, - { "nmi", OPT_STR, &opt_nmi }, - { NULL, 0, NULL } +#define V(_x) &_x, sizeof(_x) + { "console", OPT_STR, V(opt_console) }, + { "conswitch", OPT_STR, V(opt_conswitch) }, + { "com1", OPT_STR, V(opt_com1) }, + { "com2", OPT_STR, V(opt_com2) }, + { "dom0_mem", OPT_UINT, V(opt_dom0_mem) }, + { "noht", OPT_BOOL, V(opt_noht) }, + { "noacpi", OPT_BOOL, V(opt_noacpi) }, + { "nosmp", OPT_BOOL, V(opt_nosmp) }, + { "noreboot", OPT_BOOL, V(opt_noreboot) }, + { "ignorebiostables", OPT_BOOL, V(opt_ignorebiostables) }, + { "watchdog", OPT_BOOL, V(opt_watchdog) }, + { "pdb", OPT_STR, V(opt_pdb) }, + { "tbuf_size", OPT_UINT, V(opt_tbuf_size) }, + { "sched", OPT_STR, V(opt_sched) }, + { "physdev_dom0_hide", OPT_STR, V(opt_physdev_dom0_hide) }, + { "leveltrigger", OPT_STR, V(opt_leveltrigger) }, + { "edgetrigger", OPT_STR, V(opt_edgetrigger) }, + { "xenheap_megabytes", OPT_UINT, V(opt_xenheap_megabytes) }, + { "nmi", OPT_STR, V(opt_nmi) }, + { "badpage", OPT_STR, V(opt_badpage) }, + { NULL, 0, NULL, 0 } }; @@ -154,7 +162,10 @@ void cmain(multiboot_info_t *mbi) { case OPT_STR: if ( opt != NULL ) - strcpy(opts[i].var, opt); + { + strncpy(opts[i].var, opt, opts[i].len); + ((char *)opts[i].var)[opts[i].len-1] = '\0'; + } break; case OPT_UINT: if ( opt != NULL ) diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index db3a01f4fe..a57d43b9c3 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -29,6 +29,7 @@ #include #include +extern char opt_badpage[]; /********************* * ALLOCATION BITMAP @@ -137,7 +138,8 @@ unsigned long init_heap_allocator( unsigned long bitmap_start, unsigned long max_pages) { int i, j; - unsigned long bitmap_size; + unsigned long bitmap_size, bad_pfn; + char *p; memset(avail, 0, sizeof(avail)); @@ -155,40 +157,42 @@ unsigned long init_heap_allocator( /* All allocated by default. */ memset(alloc_bitmap, ~0, bitmap_size); + /* + * Process the bad-page list. Marking the page free in the bitmap will + * indicate to init_heap_pages() that it should not be placed on the + * buddy lists. + */ + p = opt_badpage; + while ( *p != '\0' ) + { + bad_pfn = simple_strtoul(p, &p, 0); + + if ( *p == ',' ) + p++; + else if ( *p != '\0' ) + break; + + if ( (bad_pfn < max_pages) && allocated_in_map(bad_pfn) ) + { + printk("Marking page %08lx as bad\n", bad_pfn); + map_free(bad_pfn, 1); + } + } + return bitmap_start + bitmap_size; } /* Hand the specified arbitrary page range to the specified heap zone. */ void init_heap_pages(int zone, struct pfn_info *pg, unsigned long nr_pages) { - int i; - unsigned long flags; + unsigned long i, pfn = page_to_pfn(pg); - spin_lock_irqsave(&heap_lock, flags); - - /* Free up the memory we've been given to play with. */ - map_free(page_to_pfn(pg), nr_pages); - avail[zone] += nr_pages; - - while ( nr_pages != 0 ) + /* Process each page in turn, skipping bad pages. */ + for ( i = 0; i < nr_pages; i++ ) { - /* - * Next chunk is limited by alignment of pg, but also must not be - * bigger than remaining bytes. - */ - for ( i = 0; i < MAX_ORDER; i++ ) - if ( ((page_to_pfn(pg) & (1 << i)) != 0) || - ((1 << (i + 1)) > nr_pages) ) - break; - - PFN_ORDER(pg) = i; - list_add_tail(&pg->list, &heap[zone][i]); - - pg += 1 << i; - nr_pages -= 1 << i; + if ( likely(allocated_in_map(pfn+i)) ) /* bad page? */ + free_heap_pages(zone, pg+i, 0); } - - spin_unlock_irqrestore(&heap_lock, flags); } diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h index d4899efe6a..e9893a2f6f 100644 --- a/xen/include/xen/lib.h +++ b/xen/include/xen/lib.h @@ -6,7 +6,7 @@ #include #ifndef NDEBUG -#define ASSERT(_p) if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , __LINE__, __FILE__); *(int*)0=0; } +#define ASSERT(_p) if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s\n", #_p , __LINE__, __FILE__); *(int*)0=0; } #else #define ASSERT(_p) ((void)0) #endif -- 2.30.2